namespace ZeBobo5.LibraryHelper.Orm
{
    public class OrmWhereFactory
    {
        private readonly string _sqlText;

        private OrmWhereFactory()
            : this("")
        {
        }

        private OrmWhereFactory(string whereCondition)
        {
            _sqlText = whereCondition;
        }

        internal string SqlText
        {
            get
            {
                return _sqlText;
            }
        }

        public OrmWhereFactory And(OrmWhereFactory secondCondition)
        {
            return new OrmWhereFactory(string.Format("{0} AND {1}", SqlText, secondCondition.SqlText));
        }

        public OrmWhereFactory Or(OrmWhereFactory secondCondition)
        {
            return new OrmWhereFactory(string.Format("{0} OR {1}", SqlText, secondCondition.SqlText));
        }

        public static OrmWhereFactory FromString(string whereCondition)
        {
            return new OrmWhereFactory(whereCondition);
        }

        public static OrmWhereFactory FromString(string whereCondition, params object[] parameters)
        {
            return FromString(string.Format(whereCondition, parameters));
        }

        #region Nested type: Comparators

        public class Comparators<A>
            where A : OrmDataElementBase<A>
        {
            public static OrmWhereFactory Equality(OrmFieldBase<A> field1, object value)
            {
                if (value == null)
                {
                    return new OrmWhereFactory(string.Format("{0}={1}", field1.FieldName, "NULL"));
                }
                return new OrmWhereFactory(string.Format("{0}={1}", field1.FieldName, value));
            }

            public static OrmWhereFactory Equality(OrmFieldBase<A> field1, string value)
            {
                return EqualityString(field1, value);
            }

            internal static OrmWhereFactory EqualityString(OrmFieldBase<A> field1, string value)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0}))=LTRIM(RTRIM('{1}'))", field1.FieldName, value));
            }

            public static OrmWhereFactory Equality(OrmFieldBase<A> field1, string value, bool invariant)
            {
                if (invariant)
                    return new OrmWhereFactory(string.Format("LTRIM(RTRIM(UPPER({0})))=LTRIM(RTRIM(UPPER('{1}')))", field1.FieldName, value));
                return Equality(field1, value);
            }

            public static OrmWhereFactory Difference(OrmFieldBase<A> field1, object value)
            {
                return new OrmWhereFactory(string.Format("{0}<>{1}", field1.FieldName, value));
            }

            public static OrmWhereFactory Difference(OrmFieldBase<A> field1, string value)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0}))<>LTRIM(RTRIM('{1}'))", field1.FieldName, value));
            }

            public static OrmWhereFactory GreaterThan(OrmFieldBase<A> field1, object value)
            {
                return new OrmWhereFactory(string.Format("{0}>{1}", field1.FieldName, value));
            }

            public static OrmWhereFactory GreaterThan(OrmFieldBase<A> field1, string value)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0}))>LTRIM(RTRIM('{1}'))", field1.FieldName, value));
            }

            public static OrmWhereFactory GreaterOrEqualsThan(OrmFieldBase<A> field1, object value)
            {
                return new OrmWhereFactory(string.Format("{0}>={1}", field1.FieldName, value));
            }

            public static OrmWhereFactory GreaterOrEqualsThan(OrmFieldBase<A> field1, string value)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0}))>=LTRIM(RTRIM('{1}'))", field1.FieldName, value));
            }

            public static OrmWhereFactory LessThan(OrmFieldBase<A> field1, object value)
            {
                return new OrmWhereFactory(string.Format("{0}<{1}", field1.FieldName, value));
            }

            public static OrmWhereFactory LessThan(OrmFieldBase<A> field1, string value)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0}))<LTRIM(RTRIM('{1}'))", field1.FieldName, value));
            }

            public static OrmWhereFactory LessOrEqualsThan(OrmFieldBase<A> field1, object value)
            {
                return new OrmWhereFactory(string.Format("{0}<={1}", field1.FieldName, value));
            }

            public static OrmWhereFactory LessOrEqualsThan(OrmFieldBase<A> field1, string value)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0}))<=LTRIM(RTRIM('{1}'))", field1.FieldName, value));
            }
        }

        #endregion

        #region Nested type: Predicates

        public class Predicates<A>
            where A : OrmDataElementBase<A>
        {
            public static OrmWhereFactory IsNull(OrmFieldBase<A> field)
            {
                return new OrmWhereFactory(string.Format("{0} IS NULL", field.FieldName));
            }

            public static OrmWhereFactory NotIsNull(OrmFieldBase<A> field)
            {
                return new OrmWhereFactory(string.Format("{0} IS NOT NULL", field.FieldName));
            }

            public static OrmWhereFactory Like(OrmFieldBase<A> field1, string value)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0})) LIKE '{1}%'", field1.FieldName, value));
            }

            public static OrmWhereFactory NotLike(OrmFieldBase<A> field1, string value)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0})) NOT LIKE '{1}%'", field1.FieldName, value));
            }

            public static OrmWhereFactory In(OrmFieldBase<A> field1, params string[] values)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0})) IN ({1})", field1.FieldName, string.Join(", ", values)));
            }

            public static OrmWhereFactory NotIn(OrmFieldBase<A> field1, params string[] values)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0})) NOT IN ({1})", field1.FieldName, string.Join(", ", values)));
            }

            public static OrmWhereFactory Between(OrmFieldBase<A> field1, object value1, object value2)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0})) BETWEEN {1} AND {2}", field1.FieldName, value1, value2));
            }

            public static OrmWhereFactory NotBetween(OrmFieldBase<A> field1, object value1, object value2)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0})) NOT BETWEEN {1} AND {2}", field1.FieldName, value1, value2));
            }

            public static OrmWhereFactory Between(OrmFieldBase<A> field1, string value1, string value2)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0})) BETWEEN '{1}' AND '{2}'", field1.FieldName, value1, value2));
            }

            public static OrmWhereFactory NotBetween(OrmFieldBase<A> field1, string value1, string value2)
            {
                return new OrmWhereFactory(string.Format("LTRIM(RTRIM({0})) NOT BETWEEN '{1}' AND '{2}'", field1.FieldName, value1, value2));
            }
        }

        #endregion
    }
}